package me.spring.cloud.common.components.mds.util;

import me.spring.cloud.common.components.mds.exception.code.DyDataSourceCode;
import me.spring.cloud.common.components.mds.strategy.DataSourceGetStrategy;
import me.spring.cloud.common.components.mds.constants.DataSourceContants;
import me.spring.cloud.common.components.mds.dynamic.DruidEntity;
import me.spring.cloud.common.components.mds.dynamic.DynamicDataSource;
import me.spring.cloud.common.components.mds.exception.DynamicDataSourceException;
import javax.sql.DataSource;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class DataSourceUtil {

  public static final String DATASOURCEGETSTRATEGY = "dataSourceGetStrategy";
  private static final ThreadLocal<String> importTmpDataSourceKey = new ThreadLocal();
  private static DataSourceGetStrategy dataSourceGetStrategy;

  static final void setDataSource2Context(String keyDataSource, DataSource importTmpDataSource) {
    //0.通过DataSourceGetStrategy策略创建数据源信息的code字段查找对应数据源的信息
    DataSource newDataSource;
    if (importTmpDataSource == null) {
      newDataSource = loadDataSource(keyDataSource);
    } else {
      newDataSource = importTmpDataSource;
      //存储临时数据源，使用结束后回收
      importTmpDataSourceKey.set(keyDataSource);
    }
    //1.检查数据源是否合法
    newDataSource = checkDataSource(newDataSource);

    //检查数据源是否能连接
    testConnection(newDataSource);

    //2.存储新的数据源到数据源集合中
    DataSourceSet.putTargetDataSourcesMap(keyDataSource, newDataSource);

    //3.同步数据源
    syncDataSource();

    //4.数据源创建完成后立即使用
    DataSourceSet.setCurrDataSource(keyDataSource);
  }

  private static void syncDataSource() {
    //1.获得已经注册的dataSourceBean并重新设置包含数据源的map
    //TODO
    DynamicDataSource dataSource = null;//(DynamicDataSource) SpringContextUtils.getContext().getBean("dataSource");
    //2.将DataSourcesMap设置回数据源
    dataSource.setTargetDataSources(DataSourceSet.getTargetDataSourcesMap());
    //3.确保后添加到targetDataSources的数据源同步到resolvedDataSources;
    dataSource.afterPropertiesSet();
  }

  /**
   * 从抽象类bean中获取数据源
   *
   * @param keyDataSource
   * @Return
   */
  private static DataSource loadDataSource(String keyDataSource) {
    if (dataSourceGetStrategy == null) {
      synchronized (DataSourceUtil.class) {
        if (dataSourceGetStrategy == null) {
          //TODO
//          if (!SpringContextUtils.getContext().containsBeanDefinition(DATASOURCEGETSTRATEGY)) {
//            throw new DynamicDataSourceException(DyDataSourceCode.OverrideGetDataSourceInfo);
//          }
//          dataSourceGetStrategy = (DataSourceGetStrategy) SpringContextUtils.getContext()
//              .getBean(DATASOURCEGETSTRATEGY);
        }
      }
    }
    return dataSourceGetStrategy.getDataSource(keyDataSource);
  }

  /**
   * 检查DataSource是否合法
   *
   * @param dataSource
   * @Return
   */
  private static DataSource checkDataSource(DataSource dataSource) {
    if (dataSource == null) {
      throw new DynamicDataSourceException(DyDataSourceCode.GetDataSourceInfoGResultNull);
    }

    long maxWait = -1l;
    try {//建立数据源之后检查是否设置了最大的等待时间
      maxWait = Long.valueOf(dataSource.getClass().getMethod("getMaxWait").invoke(dataSource).toString());
    } catch (Exception e) {
      log.error(e.getMessage(), e);
      log.error("该连接池没有实现getMaxWait方法，不能获取最大的等待的超时时间");
      throw new DynamicDataSourceException(DyDataSourceCode._getMaxWai_MethodUndefined);
    }
    if (maxWait <= 0) {
      throw new DynamicDataSourceException(DyDataSourceCode.MustSetWaitTime);
    }
    return dataSource;
  }

  /**
   * 连接测试 连接不上则抛出异常
   *
   * @Return
   */
  public final static boolean testConnection(String keyDataSource) {
    try {
      loadDataSource(keyDataSource).getConnection();
    } catch (Exception e) {
      log.error(e.getMessage(), e);
      throw new DynamicDataSourceException(DyDataSourceCode.DataBaseConnectionError);
    }
    return true;
  }

  /**
   * 连接测试 连接不上则抛出异常
   *
   * @Return
   */
  public final static boolean testConnection(DataSource dataSource) {
    try {
      dataSource.getConnection();
    } catch (Exception e) {
      log.error(e.getMessage(), e);
      throw new DynamicDataSourceException(DyDataSourceCode.DataBaseConnectionError);
    }
    return true;
  }

  /**
   * 激活默认数据源 （mainDataSource）
   */
  public static final void activateDataSource() {
    activateDataSource(DataSourceContants.MAINDATASOURCE, null);
  }

  /**
   * 激活数据源
   *
   * @param keyDataSource
   */
  public static final void activateDataSource(String keyDataSource, DataSource importTmpDataSource) {
    if (!DataSourceSet.containsDataSource(keyDataSource)) {
      if (importTmpDataSource != null) {
        log.debug("即将创建临时数据源[{}]", keyDataSource);
      }
      log.debug("正在尝试创建数据源[{}] ", keyDataSource);
      setDataSource2Context(keyDataSource, importTmpDataSource);
      log.debug("数据源[{}]创建成功", keyDataSource);
    } else {
      log.debug("[{}]数据源被激活", keyDataSource);
      DataSourceSet.setCurrDataSource(keyDataSource);
    }
  }

  /**
   * 重置为默认数据源
   */
  public static void resetDataSource(boolean tmp) {
    resetDataSource(null, tmp);
  }

  /**
   * 重置为默认数据源,删除临时数据源
   *
   * @param keyDataSource
   */
  public static void resetDataSource(String keyDataSource, boolean tmp) {
    if (keyDataSource != null) {
      log.debug("数据源[{}]使用完毕，重置为默认数据源", keyDataSource);
    } else {
      log.debug("已经重置为默认数据源");
    }
    DataSourceSet.clearCurrDataSource();
    //重置数据源时，如果是临时数据源则从dataSource上下文中清除
    if (keyDataSource != null && keyDataSource.equals(importTmpDataSourceKey.get()) && tmp) {
      DataSourceSet.removeTargetDataSourcesMap(keyDataSource);
      syncDataSource();
      log.debug("临时数据源[{}]从dataSourceBean中清除完成", keyDataSource);
    }
  }

  /**
   * 创建主数据源
   *
   * @Return
   */
  public static DataSource createMainDataSource(DruidEntity druidEntity) {
    //TODO
//    DruidDataSource datasource = new DruidDataSource();
//
//    datasource.setUrl(druidEntity.getUrl());
//    datasource.setUsername(druidEntity.getUsername());
//    datasource.setPassword(druidEntity.getPassword());
//    datasource.setDriverClassName(druidEntity.getDriverClassName());

    //configuration
//    datasource.setInitialSize(druidEntity.getInitialSize());
//    datasource.setMinIdle(druidEntity.getMinIdle());
//    datasource.setMaxActive(druidEntity.getMaxActive());
//    datasource.setMaxWait(druidEntity.getMaxWait());
//    datasource.setTimeBetweenEvictionRunsMillis(druidEntity.getTimeBetweenEvictionRunsMillis());
//    datasource.setMinEvictableIdleTimeMillis(druidEntity.getMinEvictableIdleTimeMillis());
//    datasource.setValidationQuery(druidEntity.getValidationQuery());
//    datasource.setTestWhileIdle(druidEntity.isTestWhileIdle());
//    datasource.setTestOnBorrow(druidEntity.isTestOnBorrow());
//    datasource.setTestOnReturn(druidEntity.isTestOnReturn());
//    datasource.setPoolPreparedStatements(druidEntity.isPoolPreparedStatements());
//    datasource.setMaxPoolPreparedStatementPerConnectionSize(druidEntity.getMaxPoolPreparedStatementPerConnectionSize());
//    try {
//      datasource.setFilters(druidEntity.getFilters());
//    } catch (SQLException e) {
//      log.error("druid configuration initialization filter", e);
//    }
//    datasource.setConnectionProperties(druidEntity.getConnectionProperties());
//    log.debug("默认数据源已创建");
//    return datasource;
    return null;
  }
}